package com.cngphone.AnFetion;

import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;

public class FetionReader extends Reader {
    protected InputStream stream;
    protected byte[] buffer;
    protected int bufferedlength = 0;
    protected int pos = 0;

    public FetionReader(InputStream stream) {
        this.stream = stream;
        this.buffer = new byte[1024];
    }

    @Override
    public void close() throws IOException {
        stream.close();
    }

    // public boolean WaitingAZeroByte = false;
    public synchronized FetionSIPC ReadSIPCPackage() {
        try {
            String cmdline = this.readLine().toString();
            String nvparedline = "";
            int length = 0;
            ArrayList<FetionSIPC.HeaderPair> headers = new ArrayList<FetionSIPC.HeaderPair>();
            while (!(nvparedline = this.readLine().toString()).equals("")) {
                FetionSIPC.HeaderPair h = FetionSIPC.HeaderPair.Parse(nvparedline);
                headers.add(h);
                if (h.name.equals("L")) {
                    length = Integer.valueOf(h.value.trim());
                }
            }

            String body = length > 0 ? new String(this.readString(length)) : "";
            FetionSIPC receivedpackage = new FetionSIPC(cmdline, headers, body);
            return receivedpackage;
        } catch (IOException e) {
            // e.printStackTrace();
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    protected StringBuilder readLine() throws IOException {
        StringBuilder res = new StringBuilder();
        int count = 0;
        if (this.pos >= this.buffer.length || this.bufferedlength <= 0) {
            this.pos = 0;
            this.bufferedlength = 0;
        }
        if (bufferedlength == 0) {
            count = this.stream.read(this.buffer, this.pos, this.buffer.length - pos);
            // if(this.WaitingAZeroByte == true && count == 1 && this.buffer[0] == 0)
            // {
            // WaitingAZeroByte = false;
            // FrameWork.synchronizednotify(WaitingAZeroByte);
            // return readLine();
            // }
            if (count == -1) throw new IOException();
            else bufferedlength = count;
        }
        int c = pos + bufferedlength;
        for (int i = pos; i < c; i++) {
            if (this.buffer[i] == '\n') {
                try {
                    return res.append(new String(this.buffer, pos, i > pos && this.buffer[i - 1] == '\r' ? i
                            - pos - 1 : i - pos));
                } finally {
                    bufferedlength = bufferedlength - (i - pos) - 1;
                    this.pos = i + 1;
                }
            }
        }
        res.append(new String(this.buffer, pos, bufferedlength));
        pos = 0;
        bufferedlength = 0;
        return res.append(readLine());
    }

    public byte[] readString(int len) throws IOException {
        // System.out.println("len = "+len + ":" + bufferedlength);
        if (this.pos >= this.buffer.length || this.bufferedlength <= 0) {
            this.pos = 0;
            this.bufferedlength = 0;
        }
        if (bufferedlength == 0) {
            int count = this.stream.read(this.buffer, this.pos, this.buffer.length - pos);
            if (count == -1) throw new IOException();
            else bufferedlength = count;
        }

        if (bufferedlength >= len) {
            try {
                byte[] ret = new byte[len];
                // System.out.println("a(" + len + ") = " + new String(buffer, pos, len));
                System.arraycopy(buffer, pos, ret, 0, len);
                // System.out.println("b = " + new String(ret));
                return ret;
                // return new String(this.buffer, pos, len);
            } finally {
                pos += len;
                bufferedlength -= len;
            }
        } else {
            int p = pos;
            int b = bufferedlength;
            pos = 0;
            bufferedlength = 0;
            byte[] ret = new byte[len];
            System.arraycopy(buffer, p, ret, 0, b);
            byte[] ret2 = this.readString(len - b);
            // System.out.println("c = " + new String(buffer, p, b));
            System.arraycopy(ret2, 0, ret, b, len - b);
            // System.out.println("d = " + new String(ret));
            return ret;
            // return new String(this.buffer, p, b) + this.readString(len - b);
        }

    }

    @Override
    public int read(char[] buf, int offset, int count) throws IOException {
        // TODO Auto-generated method stub
        return 0;
    }

}
